/* ------------------ 策略模式 ------------------- */
// 封装策略
let starategies = {
  isNoEmpty(value, errMsg) {
    if(value === '') return errMsg
  },
  minLength(value, length, errMsg) {
    if(value.length < length) return errMsg
  },
  isMobile(value, errMsg) {
    if(!/(^1[3-9][0-9]{9}$)/.test(value)) return errMsg
  }
}

// 添加校验规则
function validataFunc() {
  let validator = new Validator()
  validator.add(form.userName, 'isNoEmpty', '用户名不能为空')
  validator.add(form.password, 'minLength:6', '密码至少为6位数')
  validator.add(form.phone, 'isMobile', '手机号码格式不正确')

  const errMsg = validator.start()
  return errMsg
}

class Validator {
  constructor() {
    this.cache = []
  }
  add(dom, rule, errMsg) {
    let arg = rule.split(',');
    let strategy = arg.shift();
    arg.shift(dom.value);
    arg.push(errMsg);

    this.cache.push(() => {
      return starategies[strategy].apply(dom, arg)
    })
  }
  start() {
    for(let validataFunc in this.cache) {
      const msg = validataFunc();
      if(msg) {
        return msg;
      }
    }
  }
}

/* ------------------ 发布订阅模式 ------------------- */
// 定义售楼处
let salesOffices = {
  // 缓存订阅者的回调函数
  clientList: [],
  // 增加订阅者
  listen(fn) {
    this.clientList.push(fn)
  },
  // 发布消息
  trigger() {
    // 触发订阅者事件
    for(let fn of this.clientList) {
      fn.apply(this, arguments)
    }
  }
}
// A订阅
salesOffices.listen((price, squareMeter) => console.log(`A订阅价格：${price}，面积：${squareMeter}`))
// B订阅
salesOffices.listen((price, squareMeter) => console.log(`B订阅价格：${price}，面积：${squareMeter}`))

salesOffices.trigger(1600000, 80)
salesOffices.trigger(2000000, 100)

// 增加标识
let salesOffices = {
  // 缓存订阅者的回调函数
  clientList: {},
  // 增加订阅者
  listen(key, fn) {
    if(!this.clientList[key]) {
      this.clientList[key] = []
    }
    this.clientList[key].push(fn)
  },
  // 发布消息
  trigger() {
    const key = Array.prototype.shift.call(arguments)
    const fns = this.clientList[key]
    if(!fns || fns.length === 0) {
      return false
    }
    // 触发订阅者事件
    for(let fn of fns) {
      fn.apply(this, arguments)
    }
  }
}

// A订阅
salesOffices.listen('squareMeter88', price => console.log(`A订阅价格：${price}，面积：88`))
// B订阅
salesOffices.listen('squareMeter100', price => console.log(`B订阅价格：${price}，面积：100`))

salesOffices.trigger('squareMeter88', 1600000)
salesOffices.trigger('squareMeter100', 2000000)

// 通用的
// 增加标识
let event = {
  // 缓存订阅者的回调函数
  clientList: {},
  // 增加订阅者
  listen(key, fn) {
    if(!this.clientList[key]) {
      this.clientList[key] = []
    }
    this.clientList[key].push(fn)
  },
  // 发布消息
  trigger() {
    const key = Array.prototype.shift.call(arguments)
    const fns = this.clientList[key]
    if(!fns || fns.length === 0) {
      return false
    }
    // 触发订阅者事件
    for(let fn of fns) {
      fn.apply(this, arguments)
    }
  }
}
function installEvent(obj) {
  for(let i in event) {
    obj[i] = event[i]
  }
}

let salesOffices = {}
installEvent(salesOffices)

// A订阅
salesOffices.listen('squareMeter88', price => console.log(`A订阅价格：${price}，面积：88`))
// B订阅
salesOffices.listen('squareMeter100', price => console.log(`B订阅价格：${price}，面积：100`))

salesOffices.trigger('squareMeter88', 1600000)
salesOffices.trigger('squareMeter100', 2000000)


// 全局的
class Event {
  constructor() {
    this.clientList = {}
  }
  listen(key, fn) {
    if(!this.clientList[key]) {
      this.clientList[key] = []
    }
    this.clientList[key].push(fn)
  }
  trigger() {
    const key = Array.prototype.shift.call(arguments)
    const fns = this.clientList[key]
    if(!fns || fns.length === 0) {
      return false
    }
    // 触发订阅者事件
    for(let fn of fns) {
      fn.apply(this, arguments)
    }
  }
  remove(key, fn) {
    const fns = this.clientList[key]
    if(!fns) return false
    if(!fn) {
      fns && (fns.length = 0)
    } else {
      for(let i = fns.length - 1; i >= 0; i--) {
        if(fns[i] === fn) {
          fns.splice(i, 1)
        }
      }
    }
  }
}
const e = new Event()
// A订阅
e.listen('squareMeter88', price => console.log(`A订阅价格：${price}，面积：88`))
// B订阅
e.listen('squareMeter100', price => console.log(`B订阅价格：${price}，面积：100`))

e.trigger('squareMeter88', 1600000)
e.trigger('squareMeter100', 2000000)